﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using Lastfm;
using Lastfm.Scrobbling;
using Lastfm.Services;

namespace Scrobbler
{
    public class Processor
    {
        private bool _process = true;

        public event ProcessorEventHandler ErrorOccured;
        public event ProcessorEventHandler SongScrobbled;

        public void OnSongScrobbled(ProcessorEventArgs e)
        {
            ProcessorEventHandler handler = SongScrobbled;
            if (handler != null) handler(this, e);
        }

        public void OnErrorOccured(ProcessorEventArgs e)
        {
            ProcessorEventHandler handler = ErrorOccured;
            if (handler != null) handler(this, e);
        }

        public void StartProcessing(IStreamSource source)
        {
            bool firstRun = true;

            while (_process)
            {
                if (!firstRun)
                {
                    int delay = GlobalConfiguration.ProcessorDelaySecs;

                    // Run every sec and check if it has been stopped
                    for (int secs = 0; secs < delay; secs++)
                    {
                        if (!_process) { ProcessingStopped(); return; }
                        Thread.Sleep(1000);
                    }
                }

                firstRun = false;
                if (!_process) { ProcessingStopped(); return; }

                source.SongChanged += SongChanged;
                source.GetLatestSong();
            }

            ProcessingStopped();
        }

        public void StopProcessing()
        {
            _process = false;
        }

        private void SongChanged(object sender, SongEventArgs args)
        {
            var song = args.Song;

            Debug.Assert(song != null);
            Debug.Assert(!String.IsNullOrEmpty(song.Artist));
            Debug.Assert(!String.IsNullOrEmpty(song.Title));
            Debug.Assert(song.Duration != default(TimeSpan));
            Debug.Assert(song.TimeStarted != default(DateTime));

            Scrobble(song);
        }

        private void Scrobble(ISong song)
        {
            if (!GlobalConfiguration.Configuration.UseLastfm) { return; }

            if (!string.IsNullOrEmpty(GlobalConfiguration.Configuration.ProxyAddress))
            {
                var proxy = new WebProxy(GlobalConfiguration.Configuration.ProxyAddress, false) { UseDefaultCredentials = true };
                Lib.Proxy = proxy;
            }

            var username = GlobalConfiguration.Configuration.LastfmUsername;
            var password = Utilities.md5(GlobalConfiguration.Configuration.LastfmPassword);

            var entry = new Entry(song.Artist, song.Title, song.TimeStarted, PlaybackSource.NonPersonalizedBroadcast, song.Duration, ScrobbleMode.Played);
            var connection = new Connection(GlobalConfiguration.ClientId, GlobalConfiguration.ClientVersion, username, password);

            try
            {
                connection.Initialize();
                connection.Scrobble(entry);
            }
            catch (Exception ex)
            {
                OnErrorOccured(new ProcessorEventArgs(string.Format("Connection error: {0}", ex.Message)));
            }

            OnSongScrobbled(new ProcessorEventArgs(string.Format("Scrobbled: {0}", song)));
        }

        [Conditional("DEBUG")]
        private void ProcessingStopped()
        {
            // I can put breakpoint here! :P
        }
    }
}